package cn.maihe.elg.operation.centers.guogu.channel;

import cn.maihe.elg.operation.centers.guogu.channel.service.GuoGuCancelNotifyChannelService;
import cn.maihe.elg.operation.centers.guogu.channel.service.GuoGuClaimNotifyChannelService;
import cn.maihe.elg.operation.centers.guogu.channel.service.GuoGuVerifyNotifyChannelService;
import cn.maihe.elg.operation.centers.guogu.dto.GuoGuBaseRespDTO;
import cn.maihe.elg.operation.centers.guogu.dto.channel.req.GuoGuGuaranteeClaimSettlementReq;
import cn.maihe.elg.operation.centers.guogu.dto.channel.req.GuoGuGuaranteeRevokeReq;
import cn.maihe.elg.operation.centers.guogu.dto.channel.req.GuoGuVerifyNotifyReq;
import cn.maihe.elg.operation.centers.guogu.enums.GuoGuRespCodeEnum;
import cn.maihe.elg.operation.centers.supports.CenterInterfaceService;
import cn.maihe.elg.operation.centers.supports.model.bo.GuaranteeClaimSettlementResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.GuaranteeRevokeResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.PushCenterGuaranteeBo;
import cn.maihe.elg.operation.config.ZtAccountInfo;
import cn.maihe.elg.operation.exception.CenterException;
import cn.maihe.elg.operation.model.dto.InnerBaseResp;
import cn.maihe.elg.operation.model.enums.RefundOrderStatus;
import cn.maihe.elg.operation.repository.entity.*;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.InstitutionService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.guarantee.GuaranteeService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.NoticeRetryInfoService;
import cn.maihe.elg.operation.service.order.RefundOrderInfoService;
import cn.maihe.elg.operation.service.order.SpdBankNoticeService;
import cn.maihe.elg.operation.service.system.impl.OrganizationServiceImpl;
import cn.maihe.elg.operation.utils.CreateGuaranteeUtil;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.StringUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.Objects;

/**
 * @Description 南平(新点)公共资源服务中心接口服务实现
 * @Author SSX
 * @Date 2025/03/18
 */
@Service
@Slf4j
public abstract class GuoGuBaseCenterInterfaceService implements CenterInterfaceService {

    @Resource
    private GuoGuVerifyNotifyChannelService guoGuVerifyNotifyChannelService;
    @Resource
    private GuoGuCancelNotifyChannelService guoGuCancelNotifyChannelService;
    @Resource
    private GuoGuClaimNotifyChannelService guoGuClaimNotifyChannelService;
    @Resource
    private RefundOrderInfoService refundOrderInfoService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private InstitutionService institutionService;
    @Resource
    private ZtAccountInfo ztAccountInfo;
    @Resource
    private OrganizationServiceImpl organizationService;
    @Resource
    private NoticeRetryInfoService noticeRetryInfoService;
    @Resource
    private GuaranteeService guaranteeService;
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private SpdBankNoticeService spdBankNoticeService;
    @Resource
    private BidCustomerService bidCustomerService;


    @Override
    public InnerBaseResp<String> pushGuarantee(PushCenterGuaranteeBo bo) {
        GuaranteeVo vo = bo.getGuaranteeVo();
        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(vo.getAcceptOrderNo());
        Assert.notNull(acceptOrderInfo, "查无此受理订单记录");

        String applyStatus = bo.getApplyStatus();
        GuoGuVerifyNotifyReq reqDTO = new GuoGuVerifyNotifyReq();
        reqDTO.setResult(applyStatus);
        reqDTO.setTradeNo(vo.getCenterOrderId());
        if("1".equals(applyStatus)){
            reqDTO.setInsureOrderNo(vo.getGuaranteeNo());
            reqDTO.setDownloadUrl(bo.getGuarantorStatusNoticeReqDTO().getGurantee_link());
            if (vo.getGuaranteeTime() == null) {
                vo.setGuaranteeTime(new Date());
            }
            reqDTO.setInsureSuccessTime(DateUtil.formateDate(vo.getGuaranteeTime(), DateUtil.FORMAT_DATETIME));
            reqDTO.setInsureEffectTimeStart(DateUtil.formateDate(vo.getServiceBeginTime(), DateUtil.FORMAT_DATETIME));
            reqDTO.setInsureEffectTimeEnd(DateUtil.formateDate(vo.getServiceEndTime(), DateUtil.FORMAT_DATETIME));

            BidCustomerDO bidCustomer = bidCustomerService.selectById(acceptOrderInfo.getBidCustomerId());
            String payerAcctNo = bidCustomer.getBankCardNum().replace(" ", "");

            SpdBankNotice spdBankNotice = spdBankNoticeService.selectMatchPayInfoAndSectionCode(payerAcctNo, ztAccountInfo.getAccNo(), acceptOrderInfo.getGuaranteeFee(), null, acceptOrderInfo);
            if(Objects.isNull(spdBankNotice)){
                log.warn("guogu verify_notify spdBankNotice is null");
                spdBankNotice = spdBankNoticeService.selectOne(SpdBankNoticeCondition.builder().andAcceptOrderNoEq(vo.getAcceptOrderNo()).build());
            }

            log.info("spdBankNotice getAcceptOrderNo:{} getTransDate:{} getTransTime:{}", vo.getAcceptOrderNo(),spdBankNotice.getTransDate(), spdBankNotice.getTransTime());

            Date dateFromString = DateUtil.getDateFromString(spdBankNotice.getTransDate()+spdBankNotice.getTransTime(), DateUtil.FORMAT_DADETIME);
            String payTime = DateUtil.formateDate(dateFromString, DateUtil.FORMAT_DATETIME);
            reqDTO.setPayTime(payTime);
        }else {
            reqDTO.setMsg("订单取消");
        }

        if(CreateGuaranteeUtil.isUploadAllOfdAndReceive(getCenterNoEnum(),acceptOrderInfo.getClientId())){
            log.info("getGuarantorStatusNoticeReqDTO:{}", JSON.toJSONString(bo.getGuarantorStatusNoticeReqDTO()));
            reqDTO.setOfdDownloadUrl(bo.getGuarantorStatusNoticeReqDTO().getGurantee_ofd_link());
            reqDTO.setConfirmReceiptLink(bo.getGuarantorStatusNoticeReqDTO().getConfirm_receipt_link());
        }

        InnerBaseResp<String> innerBaseResp = null;

        try {
            GuoGuBaseRespDTO resp = guoGuVerifyNotifyChannelService.doRequest(acceptOrderInfo.getClientId(),getCenterNoEnum(), reqDTO);
            if (GuoGuRespCodeEnum.isSuccess(resp.getCode())) {
                innerBaseResp = InnerBaseResp.success(reqDTO.getInsureOrderNo());
            } else {
                innerBaseResp = InnerBaseResp.error(resp.getMsg());
            }
        } catch (Exception e) {
            log.error("开函结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }

        return innerBaseResp;
    }


    protected String fen2yuanString(Long fen) {
        try {
            return BigDecimal.valueOf(fen).divide(BigDecimal.valueOf(100L), 2, RoundingMode.HALF_UP).toString();
        } catch (Exception e) {
            throw CenterException.error("分转元失败", e);
        }
    }

    /**
     * 把百分比数转化成对应的小数
     *
     * @param percentageStr 需要转化的百分比字符串
     * @return 转化后的小数
     */
    protected String getPercentageToDecimal(String percentageStr) {
        try {
            if (StringUtil.isBlank(percentageStr)) {
                return new BigDecimal("0.00").toString();
            }
            String replace = percentageStr.replace("%", "");
            return new BigDecimal(replace).divide(BigDecimal.valueOf(100L), 6, RoundingMode.HALF_UP).toString();
        } catch (Exception e) {
            throw CenterException.error("百分数转小数失败", e);
        }
    }

    @Override
    public InnerBaseResp noticeGuaranteeRevokeResult(GuaranteeRevokeResultBo bo) {
        GuoGuGuaranteeRevokeReq reqDTO = new GuoGuGuaranteeRevokeReq();
        reqDTO.setTradeNo(bo.getCenterOrderId());
        reqDTO.setInsureOrderNo(bo.getGuaranteeNo());
        reqDTO.setResult(bo.getAuditPass()?"1":"0");
        reqDTO.setMsg(bo.getAuditRemark());

        GuaranteeDO guarantee = guaranteeService.getGuaranteeByGuaranteeNo(bo.getGuaranteeNo());
        Assert.notNull(guarantee, "查无此保函记录");
        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(bo.getAcceptOrderNo());
        Assert.notNull(acceptOrderInfoDO, "查无此受理订单记录");
        InnerBaseResp<String> innerBaseResp = null;
        try {
            GuoGuBaseRespDTO resp = guoGuCancelNotifyChannelService.doRequest(acceptOrderInfoDO.getClientId(),getCenterNoEnum(), reqDTO);
            if (GuoGuRespCodeEnum.isSuccess(resp.getCode())) {
                //保函编号作为序列号
                innerBaseResp = InnerBaseResp.success(bo.getGuaranteeNo());
            } else {
                innerBaseResp = InnerBaseResp.error(resp.getMsg());
            }
        } catch (Exception e) {
            log.error("保函撤销|退保结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }
        return innerBaseResp;
    }

    @Override
    public InnerBaseResp noticeGuaranteeClaimSettlementResult(GuaranteeClaimSettlementResultBo bo) {
        GuoGuGuaranteeClaimSettlementReq reqDTO = new GuoGuGuaranteeClaimSettlementReq();
        RefundOrderInfoDO refundOrderInfo = bo.getRefundOrderInfo();
        //原理赔申请接口中的 业务流水号
        reqDTO.setTradeNo(refundOrderInfo.getRefundOrderNo());
        if (refundOrderInfo.getStatus() == RefundOrderStatus.REFUNDED.getStatus()) {
            reqDTO.setResult("1");
        }
        reqDTO.setMsg(refundOrderInfo.getRemark());
        InnerBaseResp<String> innerBaseResp = null;
        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(bo.getAcceptOrderNo());
        try {
            GuoGuBaseRespDTO resp = guoGuClaimNotifyChannelService.doRequest(acceptOrderInfoDO.getClientId(),getCenterNoEnum(), reqDTO);
            if (GuoGuRespCodeEnum.isSuccess(resp.getCode())) {
                innerBaseResp = InnerBaseResp.success(refundOrderInfo.getGuaranteeNo());
            } else {
                innerBaseResp = InnerBaseResp.error(resp.getMsg());
            }
        } catch (Exception e) {
            log.error("理赔结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }
        return innerBaseResp;
    }

}